package com.csjbot.snowbotagingtest;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Message;
import android.support.annotation.IdRes;
import android.text.TextUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;

import com.csjbot.csjbase.log.Csjlogger;
import com.csjbot.snowbot_rogue.Events.ExpressionEvent;
import com.csjbot.snowbot_rogue.Events.HWTestEvent;
import com.csjbot.snowbot_rogue.platform.SnowBotManager;
import com.csjbot.snowbot_rogue.servers.slams.MoveServerMapListener;
import com.csjbot.snowbot_rogue.services.BackgroundPlayService;
import com.csjbot.snowbot_rogue.services.RogueBGService;
import com.csjbot.snowbot_rogue.utils.WeakReferenceHandler;
import com.csjbot.snowbotagingtest.base.AIUIActivity;
import com.iflytek.aiui.uartkit.UARTAgent;
import com.iflytek.aiui.uartkit.constant.UARTConstant;
import com.iflytek.aiui.uartkit.listener.EventListener;
import com.iflytek.aiui.uartkit.listener.UARTEvent;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.slamtec.slamware.robot.Pose;
import com.upcontrol.uartagent.BodyUartAgent;
import com.upcontrol.uartagent.entity.UartPacket;
import com.upcontrol.uartagent.utils.PacketBuilder;


import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android_serialport_api.SerialPort;
import butterknife.BindView;
import butterknife.OnClick;


public class TestActivity extends AIUIActivity implements MoveServerMapListener {

    private static final int LOG_MSG = 1001;
    private static final int MAP_MSG = 1002;

    private static final int LEFT_ARM = 0;
    private static final int RIGHT_ARM = 1;
    private static final int DOUBLE_ARM = 2;


    private static final int HOUR = 1110;
    private static final int MINUTE = 1111;
    private static final int SECOND = 1112;

    @BindView(R.id.tv_log)
    TextView tv_log;

    @BindView(R.id.scrollview)
    ScrollView scrollview;

    @BindView(R.id.mapImageView)
    ImageView mapImageView;

    @BindView(R.id.et_arm_count)
    EditText et_arm_count;

    @BindView(R.id.et_partol_count)
    EditText et_partol_count;

    @BindView(R.id.et_time)
    EditText et_time;

    @BindView(R.id.rg_time_type)
    RadioGroup rg_time_type;

    @BindView(R.id.tv_arm_count)
    TextView tv_arm_count;

    @BindView(R.id.tv_time)
    TextView tv_time;

    @BindView(R.id.bt_start)
    Button bt_start;

    private SnowBotManager mSnowBotManager = SnowBotManager.getInstance();

    private SpeechSynthesizer mSpeechSynthesizer = null;

    private StringBuilder mSb = new StringBuilder();

    private TestHandler mTestHandler = new TestHandler(this);

    public TestBean mTestBean = new TestBean();

    private boolean mStartTest = true;

    private int armCount = 0;

    private boolean isCustomArm;


    private int partolCount = 0;

    private int testTime = 0;

    private int testTimeType = HOUR;

    private boolean isCustomPartol;

    private int delayedTime = 0;

    private VideoRecordFragment videoRecordFragment;

    private UartPacket uartPacket = PacketBuilder.createRequireMotorSpeedPacket();

    /**
     * 发送log消息
     *
     * @param msg
     */
    public void sendLogMessage(String msg) {
        mTestHandler.obtainMessage(LOG_MSG, msg).sendToTarget();
    }

    /**
     * 发送log消息
     *
     * @param msg
     */
    public void sendLogMessage(String msg, int arg1) {
        mTestHandler.obtainMessage(LOG_MSG, arg1, 0, msg).sendToTarget();
    }

    /**
     * 开始巡逻
     */
    private void startPartol() {
        final Pose[] poses = new Pose[]{
                new Pose(0.5f, 0.5f, 0f, 0f, 0f, 0f),
                new Pose(-0.5f, 0.5f, 0f, 0f, 0f, 0f),
                new Pose(0.5f, -0.5f, 0f, 0f, 0f, 0f),
                new Pose(-0.5f, -0.5f, 0f, 0f, 0f, 0f),
        };

        mSnowBotManager.getMap(this, this);
        mTestHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isCustomPartol) {
                    mSnowBotManager.partol(Arrays.asList(poses), partolCount);
                } else {
                    mSnowBotManager.partol(Arrays.asList(poses));
                }
                mSnowBotManager.setAutoUpdateMap(true);
            }
        }, 500);

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void debugMessageRec(HWTestEvent event) {
        if (event.getTag() != 0) {
            Csjlogger.warn("======================" + event.logMsg);
            Csjlogger.warn("======================" + ((int[]) event.object)[0]);
            Csjlogger.warn("======================" + ((int[]) event.object)[1]);
            Csjlogger.warn("======================" + ((int[]) event.object)[2]);
            Csjlogger.warn("======================" + ((int[]) event.object)[3]);
            int leftSpeed = ((int[]) event.object)[2];
            int rightSpeed = ((int[]) event.object)[3];
            sendLogMessage("左轮速度:" + leftSpeed + "右轮速度:" + rightSpeed);
            if (leftSpeed > 700 || rightSpeed > 700) {
                mTestBean.setSpeeding(true);
            }
        }
    }

    private void checkSpeed() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (mStartTest) {
                    Csjlogger.debug("查询轮速串口消息");
                    BodyUartAgent.getBodyUartAgent().sendMessage(uartPacket);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }

    /**
     * 检查麦克风
     */
    private void checkAudio() {
        try {
            int bufferSize = AudioRecord.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
            AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
                    11025, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, bufferSize);
            audioRecord.startRecording();
            audioRecord.stop();
            Csjlogger.debug("麦克风打开成功");
        } catch (Exception e) {
            Csjlogger.debug("麦克风打开失败");
        }
    }

    /**
     * 检查AIUI连接
     */
    private void checkAiui() {
        String device = "";
        //获取AIUI 串口号
        SharedPreferences tools = getSharedPreferences("aiui_uart", Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = tools.edit();

        device = tools.getString("aiui_uart", "/dev/ttyS4");

        if (!device.equalsIgnoreCase("/dev/ttyS4")
                && !device.equalsIgnoreCase("/dev/ttyS3")
                && !device.equalsIgnoreCase("/dev/ttyS2")
                && !device.equalsIgnoreCase("/dev/ttyS1")
                && !device.equalsIgnoreCase("/dev/ttyS0")) {
            device = "/dev/ttyS4";
        }
        try {
            SerialPort fakeSeiral = new SerialPort(new File(device), 115200, 0, "激活AIUI");
            fakeSeiral = null;
        } catch (IOException e) {
            e.printStackTrace();
        }

        //  初始化 AIUI 的 agent
        UARTAgent.createAgent(this, device, 115200, new EventListener() {
            @Override
            public void onEvent(UARTEvent event) {
                switch (event.eventType) {
                    case UARTConstant.EVENT_INIT_SUCCESS:
                        mTestBean.setAiuiStatus(true);
                        break;
                    case UARTConstant.EVENT_INIT_FAILED:
                        mTestBean.setAiuiStatus(false);
                        break;
                }
            }
        });
    }

    @Override
    public void getMap(Bitmap map) {
        Message msg = mTestHandler.obtainMessage();
        Bundle bundle = new Bundle();
        bundle.putParcelable("bitmap", map);
        msg.setData(bundle);
        msg.what = 0;
        mTestHandler.sendMessage(msg);
    }

    private void startTestInit() {
        mTestBean.clearAllData();
        try {
            String armStr = et_arm_count.getText().toString().trim();
            String partolStr = et_partol_count.getText().toString().trim();
            String testTimeStr = et_time.getText().toString().trim();
            if (!TextUtils.isEmpty(armStr)) {
                armCount = Integer.parseInt(armStr);

            }
            if (!TextUtils.isEmpty(partolStr)) {
                partolCount = Integer.parseInt(partolStr);

            }
            if(!TextUtils.isEmpty(testTimeStr)){
                testTime = Integer.parseInt(testTimeStr);
            }
        } catch (Exception e) {
            armCount = 0;
            partolCount = 0;
            testTime = 0;
        }
        isCustomArm = armCount > 0;
        isCustomPartol = partolCount > 0;
        mStartTest = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        bt_start.setClickable(true);
    }

    @OnClick(R.id.bt_start)
    public void startTest() {
        bt_start.setClickable(false);
        // 开始测试
//        cpuTest();
        startTestInit();
        checkSpeed();
        checkAiui();
        checkAudio();
        startPartol();
        startAction();
        startCamera();
        checkTime();


    }

    private void checkTime(){
        if(testTime <= 0){
            return;
        }
        switch (testTimeType){
            case HOUR:
                delayedTime = testTime*(60*60*1000);
                break;
            case MINUTE:
                delayedTime = testTime*(60*1000);
                break;
            case SECOND:
                delayedTime = testTime*(1000);
                break;
            default:
                break;
        }
        mTestHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                stopTest();
            }
        },delayedTime);

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                tv_time.post(new Runnable() {
                    @Override
                    public void run() {
                        delayedTime-=1000;
                        int hour = delayedTime /(60*60*1000);
                        int minute = (delayedTime - hour*60*60*1000)/(60*1000);
                        int seconds = (delayedTime - hour*60*60*1000 - minute*60*1000)/1000;
                        tv_time.setText("剩余时间:"+hour+":小时 "+minute+"分 "+seconds+"秒");
                    }
                });

            }
        };
        Timer timer = new Timer();
        timer.schedule(task,1000,1000);
    }

    private void startCamera(){
        videoRecordFragment.startAction();
    }

    /**
     * 增加cpu工作压力
     */
    private void cpuTest(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;
                while(i<200){
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            int j = 0;
                            while(true){
                                j++;
                            }
                        }
                    }).start();
                    i++;
                }
            }
        }).start();
    }


    @OnClick(R.id.bt_exit)
    public void exitTest() {
        mSnowBotManager.stopPartol();
        RogueUtils.kill(getPackageName());
    }

    @OnClick(R.id.bt_stop)
    public void stopTest() {
        // 停止测试
        videoRecordFragment.stopAction();
        mSnowBotManager.stopPartol();
        mStartTest = false;
        mTestBean.setPartolErrorCount(mSnowBotManager.getErrorCount());
        mTestBean.setTag(stampToDate(String.valueOf(System.currentTimeMillis())));
        // 查看测试结果
        Intent intent = new Intent(TestActivity.this, TestInfoActivity.class);
        Bundle bundle = new Bundle();
        bundle.putSerializable("testinfo", mTestBean);
        intent.putExtras(bundle);
        startActivity(intent);
    }

    @Override
    public void afterViewCreated(Bundle savedInstanceState) {

        startServices();

        videoRecordFragment = (VideoRecordFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_video_record);

        /**
         * 干死自动检测软件,防止抢串口
         */
        RogueUtils.kill("com.csjbot.automated_test");

        RogueUtils.kill("com.csjbot.snowbot");

        init();

    }

    private void init(){
        initSpeak();
        rg_time_type.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
                switch (i){
                    case R.id.rb_hour:
                        testTimeType = HOUR;
                        break;
                    case R.id.rb_minute:
                        testTimeType  = MINUTE;
                        break;
                    case R.id.rb_second:
                        testTimeType  = SECOND;
                        break;
                }
            }
        });
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒");
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     * 开始一些动作(说话,摇动手臂,变换表情)
     */
    private void startAction() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                    swingArm();
                    switchExpression();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void startServices() {
        Intent rogueBGServiceIntent = new Intent(this, RogueBGService.class);
        Intent backgroundPlayService = new Intent(this, BackgroundPlayService.class);
        startService(backgroundPlayService);
        startService(rogueBGServiceIntent);
    }

    private void initSpeak(){
        if (mSpeechSynthesizer == null) {
            mSpeechSynthesizer = SpeechSynthesizer.createSynthesizer(this, new InitListener() {
                @Override
                public void onInit(int i) {

                }
            });
            mSpeechSynthesizer.setParameter(SpeechConstant.PARAMS, null);
            //设置云端合成引擎
            mSpeechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
            // 设置在线合成发音人:xiaoyan
            mSpeechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "nannan");
            //设置合成语速:50
            mSpeechSynthesizer.setParameter(SpeechConstant.SPEED, "70");
            //设置合成音调:50
            mSpeechSynthesizer.setParameter(SpeechConstant.PITCH, "70");
            //设置合成音量:50
            mSpeechSynthesizer.setParameter(SpeechConstant.VOLUME, "80");
        }
    }

    /**
     * 说话
     */
    private void speak(int type) {
        String speakStr = "";
        // 执行说话
        switch (type){
            case 0:
                speakStr = "正在摆动左手臂";
                break;
            case 1:
                speakStr = "正在摆动右手臂";
                break;
            case 2:
                speakStr = "正在摆动双手臂";
                break;
            default:
                break;
        }
        mSpeechSynthesizer.startSpeaking(speakStr, new DefaultSynthesizerListener());
        // 发送执行说话的log
        sendLogMessage("正在执行说话...");
    }

    /**
     * 不停变换表情
     */
    private void switchExpression() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;
                while (mStartTest) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 发送更换表情事件
                    postEvent(new ExpressionEvent(i));
                    // 发送更换表情Log
                    sendLogMessage("正在更换表情...");
                    mTestBean.addExpressionCount(1);
                    i++;
                    if (i > 10) {
                        i = 0;
                    }
                }
            }
        }).start();
    }

    /**
     * 摇动手臂
     *
     * @param tag
     */
    private void swingArm(int tag) {
        switch (tag) {
            case 0:
                // 摇动左臂.
                mSnowBotManager.swingLeftArm((byte)0x01);
                break;
            case 1:
                // 摇动右臂.
                mSnowBotManager.swingRightArm((byte)0x01);
                break;
            case 2:
                // 摇动双臂.
                mSnowBotManager.swingDoubleArm((byte)0x01);
                break;
        }

    }
    int armNumber = 0;

    /**
     * 不停的摆动手臂
     */
    private void swingArm() {
        new Thread(new Runnable() {
            /**
             * 线程睡眠
             */
            private void sleep(int time) {
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void run() {
                int index = 0;
                while (isCustomArm ? index < armCount : mStartTest) {
                    if(isCustomArm){
                        armNumber = armCount - index;
                        tv_arm_count.post(new Runnable() {
                            @Override
                            public void run() {
                                tv_arm_count.setText("剩余手臂次数:"+armNumber);
                            }
                        });

                    }
                    // 摇动左臂.
                    swingArm(LEFT_ARM);
                    speak(LEFT_ARM);
                    // 发送摇动左臂Log
                    sendLogMessage("正在摇动左臂...");
                    sleep(3500);
                    swingArm(LEFT_ARM);
                    mTestBean.addLeftArmCount(1);
                    sleep(7000);

                    // 摇动右臂.
                    swingArm(RIGHT_ARM);
                    speak(RIGHT_ARM);
                    // 发送摇动右臂Log
                    sendLogMessage("正在摇动右臂...");
                    sleep(3500);
                    swingArm(RIGHT_ARM);
                    mTestBean.addRightArmCount(1);
                    sleep(7000);

                    // 摇动双臂.
                    swingArm(DOUBLE_ARM);
                    speak(DOUBLE_ARM);
                    // 发送摇动双臂Log
                    sendLogMessage("正在摇动双臂...");
                    sleep(3500);
                    swingArm(DOUBLE_ARM);
                    mTestBean.addDoubleArmCount(1);
                    sleep(7000);

                    index+=1;
                }
            }
        }).start();
    }

    /**
     * 显示log
     *
     * @param msg
     */
    public void setLogMsg(Message msg) {
        if (msg.arg1 == 10) {
            mTestBean.setCameraOpenStatus(true);
        } else if (msg.arg1 == 11) {
            mTestBean.setCameraOpenStatus(false);
        }
        // 追加log信息
        mSb.append(msg.obj.toString() + "\n");
        tv_log.setText(mSb.toString());
        // 延时300毫秒后ScrollView滑动到底部
        mTestHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                scrollview.fullScroll(ScrollView.FOCUS_DOWN);
            }
        }, 300);
    }

    /**
     * 显示地图
     *
     * @param msg
     */
    public void setMapImageView(Message msg) {
        Bitmap bm = msg.getData().getParcelable("bitmap");
        mapImageView.setImageBitmap(bm);
    }

    @Override
    public void setListener() {

    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_test;
    }

    private class DefaultSynthesizerListener implements SynthesizerListener {
        @Override
        public void onSpeakBegin() {
//            BusFactory.getBus().post(new ExpressionEvent(Constant.Expression.EXPRESSION_SPEAK));
        }

        @Override
        public void onBufferProgress(int i, int i1, int i2, String s) {

        }

        @Override
        public void onSpeakPaused() {

        }

        @Override
        public void onSpeakResumed() {

        }

        @Override
        public void onSpeakProgress(int i, int i1, int i2) {

        }

        @Override
        public void onCompleted(SpeechError speechError) {
            mTestBean.addSpeakCount(1);
        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {

        }
    }

    public static class TestHandler extends WeakReferenceHandler<TestActivity> {

        TestHandler(TestActivity reference) {
            super(reference);
        }

        @Override
        protected void handleMessage(TestActivity reference, Message msg) {
            switch (msg.what) {
                case MAP_MSG:
                    // 设置地图显示
                    reference.setMapImageView(msg);
                    break;
                case LOG_MSG:
                    // 设置Log显示
                    reference.setLogMsg(msg);
                    break;
                default:
                    break;
            }
        }

    }
}
